package com.ydl.iec.demo;

import com.ydl.iec.iec104.enums.QualifiersEnum;
import com.ydl.iec.iec104.enums.TypeIdentifierEnum;
import com.ydl.iec.iec104.message.MessageDetail;
import com.ydl.iec.iec104.message.MessageInfo;
import com.ydl.iec.iec104.server.handler.ChannelHandler;
import com.ydl.iec.util.ByteUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.util.*;
import java.util.regex.Pattern;

@Slf4j
@Data
@Deprecated
public class SenderThread implements Runnable, Closeable {
    private final ChannelHandler ctx;
    private final int sourceId;
    private final int checkpoint;
    private final int stateId;
    private final int switchId;
    private final short terminalAddress;
    private final File dataFile;
    private final String[] ITEM_LABEL = {"ap","soc","soh","charge","discharge","max.charge","max.discharge"};
    private final int[] ITEM_ADDR = {0,0,0,0,0,0,0};
    private boolean running = false;
    private Map<String,String> buffer = new HashMap<>();

    public SenderThread(ChannelHandler ctx,int sourceId){
        this.ctx = ctx;
        this.sourceId = sourceId;
        this.checkpoint = Integer.parseInt(Test.config.getProperty("checkpoint"));
        this.terminalAddress = Short.parseShort(Test.config.getProperty("terminal.id"));
        this.stateId = Integer.parseInt(Test.config.getProperty(sourceId + ".state"));
        this.switchId = Integer.parseInt(Test.config.getProperty(sourceId + ".switch"));
        for(int i = 0; i < ITEM_LABEL.length; i++){
            String id = Test.config.getProperty(sourceId + "." + ITEM_LABEL[i]);
            ITEM_ADDR[i] = Integer.parseInt(id);
        }
        String path = System.getProperty("user.dir");
        this.dataFile = new File(path,String.format("%s.properties",sourceId));
    }
    @Override
    public void run() {
        while (running){
            Properties conf = loadProperties(dataFile);
            String newValue = conf.getProperty("state");
            String oldValue = buffer.get("state");
            if(newValue == null || "".equals(newValue.trim())){
                //TODO: Dong忽略
            }else if(!newValue.equals(oldValue)){
                buffer.put("state",newValue);
                sendState(newValue,(short)1);
            }

            // TODO: Dong 功能验证代码 不作为正式使用
            boolean isChanged = false;
            for (String s : ITEM_LABEL) {
                String newMetric = conf.getProperty(s, "0").replaceAll("\\s+", "");
                if (!Pattern.compile("^(-)?\\d*(\\.\\d+)?$").matcher(newMetric).matches()) {
                    newMetric = "0";
                }
                String oldMetric = buffer.get(s);
                if (oldMetric == null || !newMetric.equals(oldMetric)) {
                    buffer.put(s, newMetric);
                    isChanged = true;
                }
            }
            if(isChanged){
                //有变动，发送数据
                sendMetric((short)1);//主动、周期上送
//                sendMetricAnother((short)1);
            }
            try {
                Thread.sleep(checkpoint);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        log.info("{}号资源运行结束.",this.sourceId);
    }

    public void start(){
        this.running = true;
    }
    public boolean isRunning(){
        return this.running;
    }
    @Override
    public void close() {
        this.running = false;
    }

    private Properties loadProperties(File dataFile){
        Properties sourceData = new Properties();
        if(dataFile.exists()){
            try{
                FileInputStream fis = new FileInputStream(dataFile);
                sourceData.load(fis);
            }catch (Exception e){
                e.printStackTrace();
            }
        }else{
            log.error("{}号资源的配置文件不存在，系统将不会上送资源状态及数据",dataFile.getName());
        }
        return sourceData;
    }

    private void sendState(String state,short transferReason){
        TypeIdentifierEnum typeIdentifierEnum = TypeIdentifierEnum.onePointTeleindication;
        boolean isContinuous = false;
        byte[] control = new byte[4];
        boolean isTest = false;
        boolean isPN = true;

        // 消息地址 总召唤地址为0
        int messageAddress = stateId;
        QualifiersEnum qualifiers = QualifiersEnum.getQualifiersEnum(TypeIdentifierEnum.onePointTeleindication,(byte)1);
        List<MessageInfo> messages = new ArrayList<>();
        MessageInfo message = new MessageInfo();
//        message.setQualifiersType(qualifiers);
        message.setMessageAddress(stateId);
//        byte[] info = {op};
        byte x = (byte)Integer.parseInt(state);
        byte[] info = {x};
        message.setMessageInfos(info);
        messages.add(message);
        MessageDetail ruleDetail104 = new MessageDetail(control, typeIdentifierEnum, isContinuous, isTest, isPN, transferReason,
                terminalAddress, messageAddress, messages, null, qualifiers);
        ctx.writeAndFlush(ruleDetail104);
    }

    private void sendMetric(short transferReason){
        TypeIdentifierEnum typeIdentifierEnum = TypeIdentifierEnum.shortFloatingPointTelemetry;
        boolean isContinuous = true;
//        short transferReason = 7;
        // true：1 ; false ： 0
        byte[] control = {0,0,0,0};
        boolean isTest = false;
        // true:0 false;1
        boolean isPN = true;

        // 消息地址 总召唤地址为0
        int messageAddress = ITEM_ADDR[0];

        QualifiersEnum qualifiers = QualifiersEnum.qualityQualifiers;
        List<MessageInfo> messages = new ArrayList<>();
        for(int i = 0; i < ITEM_LABEL.length; i++){
            MessageInfo message = new MessageInfo();
            String val = buffer.get(ITEM_LABEL[i]);
            float f = Float.parseFloat(val);
            message.setMessageAddress(ITEM_ADDR[i]);
            byte[] data = ByteUtil.floatToBytes(f);
            message.setMessageInfos(data);
            message.setQualifiersType(QualifiersEnum.qualityQualifiers);
            messages.add(message);
        }

        MessageDetail ruleDetail104 = new MessageDetail(control, typeIdentifierEnum, isContinuous, isTest, isPN, transferReason,
                terminalAddress, messageAddress, messages, null, qualifiers);
        ctx.writeAndFlush(ruleDetail104);
    }

    private void sendMetricAnother(short transferReason){
        TypeIdentifierEnum typeIdentifierEnum = TypeIdentifierEnum.shortFloatingTimeTelemetry;
        boolean isContinuous = true;
//        short transferReason = 7;
        // true：1 ; false ： 0
        byte[] control = {0,0,0,0};
        boolean isTest = false;
        // true:0 false;1
        boolean isPN = true;

        // 消息地址 总召唤地址为0
        int messageAddress = ITEM_ADDR[0];

        QualifiersEnum qualifiers = QualifiersEnum.shortFloatTime;
        List<MessageInfo> messages = new ArrayList<>();
        for(int i = 0; i < ITEM_LABEL.length; i++){
            MessageInfo message = new MessageInfo();
            String val = buffer.get(ITEM_LABEL[i]);
            float f = Float.parseFloat(val);
            log.info("数据值为：{}",f);
            message.setMessageAddress(ITEM_ADDR[i]);
            byte[] data = ByteUtil.floatToBytes(f);
            message.setMessageInfos(data);
            message.setQualifiersType(QualifiersEnum.qualityQualifiers);
            messages.add(message);
        }

        MessageDetail ruleDetail104 = new MessageDetail(control, typeIdentifierEnum, isContinuous, isTest, isPN, transferReason,
                terminalAddress, messageAddress, messages, null, qualifiers);
        ctx.writeAndFlush(ruleDetail104);
    }

    private void sendTotalCall(){
        TypeIdentifierEnum typeIdentifierEnum = TypeIdentifierEnum.shortFloatingTimeTelemetry;
        boolean isContinuous = false;
        short transferReason = 7;
        // true：1 ; false ： 0
        byte[] control = {0,0,0,0};
        boolean isTest = false;
        // true:0 false;1
        boolean isPN = true;

        // 消息地址 总召唤地址为0
        int messageAddress = ITEM_ADDR[0];

        QualifiersEnum qualifiers = QualifiersEnum.shortFloatTime;
        List<MessageInfo> messages = new ArrayList<>();
        for(int i = 0; i < ITEM_LABEL.length; i++){
            MessageInfo message = new MessageInfo();
            String val = buffer.get(ITEM_LABEL[i]);
            float f = Float.parseFloat(val);
            log.info("数据值为：{}",f);
            message.setMessageAddress(ITEM_ADDR[i]);
            byte[] data = ByteUtil.floatToBytes(f);
            message.setMessageInfos(data);
            message.setQualifiersType(QualifiersEnum.qualityQualifiers);
            messages.add(message);
        }

        MessageDetail ruleDetail104 = new MessageDetail(control, typeIdentifierEnum, isContinuous, isTest, isPN, transferReason,
                terminalAddress, messageAddress, messages, null, qualifiers);
        ctx.writeAndFlush(ruleDetail104);
    }
}
